////////////////////////////////////////////////////////////////////////////////
// Copyright 2005 CORE Solutions Limited
// All rights reserved.
// PROPRIETARY AND CONFIDENTIAL INFORMATION.
// Use is subject to license terms.
//
// FUNCTION ID      :   
// AUTHOR           :    
// DATE CREATE      :   
// DESCRIPTION      :   
//                  :   
//                  :   
//                  :   
//
// MODIFICATION HISTORY:
// DATE         AUTHOR          VERSION NO.         COMMENT
// -----------  --------------  ------------------  -------------------
// 2006/04/26   Ric Yik         1.0                 BugZilla #5510
//
//
////////////////////////////////////////////////////////////////////////////////

package com.erp.framework.model.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;

import com.erp.app.common.ProjectConstants;
import com.erp.framework.exceptions.CreateRecordException;
import com.erp.framework.exceptions.DeleteRecordException;
import com.erp.framework.exceptions.FindRecordException;
import com.erp.framework.exceptions.ModifyRecordException;
import com.erp.framework.model.criteria.SimpleBaseSrchCriteria;
import com.erp.framework.model.pk.SimpleBasePk;
import com.erp.framework.model.vo.ChildList;
import com.erp.framework.model.vo.SimpleBaseVo;
import com.erp.framework.util.logger.Logger;

//ERP: now the code is same/similar as SimplePageEditStyleDao
//but need to modify in the future
public abstract class SimpleSearchMaintStyleDao extends SimpleBaseDao {

    public void setMaxRows(Statement stmt) throws Exception {
        stmt.setMaxRows(ProjectConstants.DB_ROW_NUM);
    }

    public abstract ChildList selectByParent(SimpleBaseVo parent, Connection conn) throws FindRecordException;

    public Collection findByCriteria(Object obj, Connection conn) throws FindRecordException {
        // set the search criteria class
        SimpleBaseSrchCriteria criteria = (SimpleBaseSrchCriteria) obj;
        Statement stmt = null;
        ResultSet rs = null;
        ArrayList rslt = new ArrayList();

        try {
            String query = sqlQuery(criteria);
            super.logSqlQuery(query);
            stmt = conn.createStatement();
            setMaxRows(stmt);
            rs = stmt.executeQuery(query);

            if (rs != null) {
                while (rs.next()) {
                    rslt.add(criteria.isSearchResult() ? getSearchResultSetValues(rs) : getResultSetValues(rs));
                }
            }

        } catch (Exception e) {
            Logger.logExceptions(this, e);
            throw new FindRecordException(e.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
            } catch (Exception e) {
                Logger.logExceptions(this, e);
            }
            try {
                if (stmt != null)
                    stmt.close();
            } catch (Exception e) {
                Logger.logExceptions(this, e);
            }
        }
        return rslt;
    }

    public ChildList selectByParent(SimpleBaseVo parent, Class childClazz, Connection conn) throws FindRecordException {
        PreparedStatement pStmt = null;
        ResultSet rs = null;
        ChildList rslt = new ChildList(childClazz);

        try {
        	String query = sqlList();
            super.logSqlQuery(query);
            pStmt = conn.prepareStatement(query);
            setValuesForList(pStmt, parent.getPrimaryKey());

            rs = pStmt.executeQuery();

            while (rs.next()) {
                SimpleBaseVo childVO = (SimpleBaseVo) getResultSetValues(rs);
                childVO.setParent(parent);
                childVO.setIsExisting(true);
                childVO.setIsDirty(false);

                rslt.add(childVO);
            }
        } catch (SQLException sqe) {
            throw new FindRecordException(sqe.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (pStmt != null)
                    pStmt.close();
            } catch (SQLException sqe) {
                Logger.logExceptions(this, sqe);
            }
        }
        return rslt;
    }

    public SimpleBaseVo findByPrimaryKey(Object obj, Connection conn) throws FindRecordException {
        PreparedStatement pStmt = null;
        ResultSet rs = null;
        SimpleBaseVo model = null;
        SimpleBasePk pk = (SimpleBasePk) obj;

        try {
        	long hdrstart = System.currentTimeMillis();
        	
        	String query = sqlFind();
            super.logSqlQuery(query);
            pStmt = conn.prepareStatement(query);
            setValuesForFind(pStmt, pk);

            rs = pStmt.executeQuery();
            boolean modelNotNull = false;

            if (rs.next()) {
                model = (SimpleBaseVo) getResultSetValuesForFind(rs);                
                modelNotNull = true;
            }
            
            if(modelNotNull){
            	long hdrend = System.currentTimeMillis();
                Logger.debug(this, "findByPrimaryKey(), Load header, "
                		+ model.getClass().getName()	
                		+ ", in " + ((hdrend-hdrstart)/100.000) + " seconds");
            }
                        
        } catch (SQLException sqe) {
            throw new FindRecordException(sqe.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (pStmt != null)
                    pStmt.close();
            } catch (SQLException sqe) {
                Logger.logExceptions(this, sqe);
            }
        }
        return model;
    }

    public void insert(SimpleBaseVo bizModel, Connection conn) throws CreateRecordException {
        PreparedStatement pStmt = null;
        ResultSet rs = null;
        try {
        	String query = sqlInsert();
            super.logSqlQuery(query);
            pStmt = conn.prepareStatement(query);
            setValuesForInsert(pStmt, bizModel);

            int count = pStmt.executeUpdate();
            if (count != 1)
                throw new SQLException("Unable to insert " + bizModel.getPrimaryKey());
        } catch (SQLException sqe) {
            throw new CreateRecordException(sqe.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (pStmt != null)
                    pStmt.close();
            } catch (SQLException sqe) {
                Logger.logExceptions(this, sqe);
            }
        }
    }

    public void update(SimpleBaseVo bizModel, Connection conn) throws ModifyRecordException {
        PreparedStatement pStmt = null;
        ResultSet rs = null;

        try {
        	String query = sqlUpdate();
            super.logSqlQuery(query);
            pStmt = conn.prepareStatement(query);
            setValuesForModify(pStmt, bizModel);

            int count = pStmt.executeUpdate();
            if (count != 1) {                
                throw new SQLException("Unable to update " + bizModel.getPrimaryKey());
            }
        } catch (SQLException sqe) {
            throw new ModifyRecordException(sqe.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (pStmt != null)
                    pStmt.close();
            } catch (SQLException sqe) {
                Logger.logExceptions(this, sqe);
            }
        }
    }

    public void remove(SimpleBaseVo bizModel, Connection conn) throws DeleteRecordException {
        PreparedStatement pStmt = null;
        ResultSet rs = null;
        try {
//            if(bizModel.isDeleteForever()){
//                pStmt = conn.prepareStatement(sqlPurge());
//                setValuesForPurge(pStmt, bizModel);
//            } else {
        	String query = sqlDelete();
            super.logSqlQuery(query);
            pStmt = conn.prepareStatement(query);
//                setValuesForDelete(pStmt, bizModel);
//            }
            setValuesForDelete(pStmt, bizModel);

            int count = pStmt.executeUpdate();
            if (count != 1) {
                Logger.warn(this, "Execute Update record count != 1: " + count);
            }
        } catch (SQLException sqe) {
            throw new DeleteRecordException(sqe.getMessage());
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (pStmt != null)
                    pStmt.close();
            } catch (SQLException sqe) {
                Logger.logExceptions(this, sqe);
            }
        }
    }

    protected abstract String sqlInsert();

    protected abstract void setValuesForInsert(PreparedStatement pStmt, Object obj) throws SQLException;

    protected abstract String sqlUpdate();

    protected abstract void setValuesForModify(PreparedStatement pStmt, Object obj) throws SQLException;

    protected abstract String sqlDelete();

    protected abstract void setValuesForDelete(PreparedStatement pStmt, Object obj) throws SQLException;

//    protected abstract String sqlPurge();
//
//    protected abstract void setValuesForPurge(PreparedStatement pStmt, Object obj) throws SQLException;
    
    /*
    protected String sqlPurge(){
        return sqlDelete();
    }

    protected void setValuesForPurge(PreparedStatement pStmt, Object obj) throws SQLException {
        setValuesForDelete(pStmt, obj);
    }
    */
    
    protected abstract String sqlFind();

    protected abstract void setValuesForFind(PreparedStatement pStmt, Object obj) throws SQLException;

    protected abstract String sqlList();

    protected abstract void setValuesForList(PreparedStatement pStmt, Object obj) throws SQLException;

    protected abstract SimpleBaseVo getResultSetValues(ResultSet rs) throws SQLException;

    protected SimpleBaseVo getSearchResultSetValues(ResultSet rs) throws SQLException {
        return getResultSetValues(rs);
    }

    protected SimpleBaseVo getResultSetValuesForFind(ResultSet rs) throws SQLException {
        return getResultSetValues(rs);
    }

    protected String sqlQuery(SimpleBaseSrchCriteria criteria) {
        return "";
    }
}
